﻿using System;
using System.Linq;
using System.ServiceProcess;
using System.Threading;
using Biz.Buffer;
using Biz.EF.Gateway.Monitor;
using Biz.EF.Platform;
using Biz.Process;
using Hjt212Parser;
using log4net;

namespace Biz
{
    public partial class BizProcessor : ServiceBase
    {
        private readonly ILog _log = LogManager.GetLogger(typeof(BizProcessor));
        int milliSeconds = 1000;
        public BizProcessor()
        {
            InitializeComponent();
        }
        //test
        public void Main()
        {
            OnStart(null);
        }
        /// <summary>
        /// 各路线程
        /// </summary>
        /// <param name="args"></param>
        protected override void OnStart(string[] args)
        {
            //启动各路线程
            //数据解析
            new Thread(ProcessData).Start();
            //new Thread(Process2051).Start();
            //new Thread(Process2061).Start();
            //new Thread(Process2031).Start();
            //响应指令9011、9012、9014
            new Thread(Process901X).Start();
            //剩余其他指令
            new Thread(ProcessOther).Start();
            //命令下发
            new Thread(ProcessDownCmds).Start();
            //数据下发
            //new Thread(ProcessDownData2011).Start();
            //new Thread(ProcessDownData2051).Start();
            //new Thread(ProcessDownData2061).Start();
            new Thread(ProcessTriger).Start();
            new Thread(Charging).Start();
            _log.Info("各路线程启动完成...");
        }
        protected override void OnStop()
        {
            _log.Info("The processor Stoped!");
            Environment.Exit(0);
        }
        private void ProcessData(object state)
        {
            while (true)
            {
                new UplineInstructionProcessorFacade().Process("2011");
                new UplineInstructionProcessorFacade().Process("2051");
                new UplineInstructionProcessorFacade().Process("2061");
                new UplineInstructionProcessorFacade().Process("2031");
                UplineStatusInstruction.ProcessStatusByBiz();
                ThreadUtil.Sleep(milliSeconds);

            }
            // ReSharper disable once FunctionNeverReturns
        }
        //private void Process2051(object state)
        //{
        //    while (true)
        //    {
        //        try
        //        {
        //            new UplineInstructionProcessorFacade().Process("2051");
        //        }
        //        catch (Exception ex)
        //        {
        //            _log.Error(ex);
        //        }
        //        finally
        //        {
        //            ThreadUtil.Sleep(milliSeconds);
        //        }
        //    }
        //    // ReSharper disable once FunctionNeverReturns
        //}
        //private void Process2061(object state)
        //{
        //    while (true)
        //    {
        //        try
        //        {
        //            new UplineInstructionProcessorFacade().Process("2061");
        //        }
        //        catch (Exception ex)
        //        {
        //            _log.Error(ex);
        //        }
        //        finally
        //        {
        //            ThreadUtil.Sleep(milliSeconds);
        //        }
        //    }
        //    // ReSharper disable once FunctionNeverReturns
        //}
        //private void Process2031(object state)
        //{
        //    while (true)
        //    {
        //        try
        //        {
        //            new UplineInstructionProcessorFacade().Process("2031");
        //        }
        //        catch (Exception ex)
        //        {
        //            _log.Error(ex);
        //        }
        //        finally
        //        {
        //            ThreadUtil.Sleep(milliSeconds);
        //        }
        //    }
        //    // ReSharper disable once FunctionNeverReturns
        //}

        private void Process901X(object state)
        {
            while (true)
            {
                try
                {
                    new UplineInstructionProcessorFacade().Process("9011");
                    new UplineInstructionProcessorFacade().Process("9012");
                    new UplineInstructionProcessorFacade().Process("9014");
                }
                catch (Exception ex)
                {
                    _log.Error(ex);
                }
                finally
                {
                    ThreadUtil.Sleep(milliSeconds);
                }
            }
            // ReSharper disable once FunctionNeverReturns
        }
        private void ProcessOther(object state)
        {
            while (true)
            {
                new UplineInstructionProcessorFacade().Process("1011");
                new UplineInstructionProcessorFacade().Process("2072");
                new UplineInstructionProcessorFacade().Process("3097");
                new UplineInstructionProcessorFacade().Process("3052");
                new UplineInstructionProcessorFacade().Process("4012");
                new UplineInstructionProcessorFacade().Process("3071");
                new UplineInstructionProcessorFacade().Process("3081");
                new UplineInstructionProcessorFacade().Process("3082");
                new UplineInstructionProcessorFacade().Process("0000");
                new UplineInstructionProcessorFacade().Process("9999");

                ThreadUtil.Sleep(milliSeconds);

            }
            // ReSharper disable once FunctionNeverReturns
        }

        private void ProcessDownCmds(object state)
        {

            while (true)
            {
                try
                {

                    using (var gCtx = new GatewayMonitorContext())
                    using (var pCtx = new PlatformContext())
                    {
                        DownlineCmdInstructionTotal.Gen3051_3071CmdToGateway(gCtx, pCtx);
                        DownlineCmdInstructionTotal.Gen3094CmdToGateway(gCtx, pCtx);
                        DownlineCmdInstructionTotal.Gen3091CmdToGateway(gCtx, pCtx);
                        DownlineCmdInstructionTotal.Gen5012CmdToGatewayAdminAndMaintain(gCtx, pCtx);
                        //DownlineCmdInstructionTotal.Gen5012CmdToGatewayOld(gCtx, pCtx);
                        DownlineCmdInstructionTotal.Gen3097CmdToGateway(gCtx, pCtx);

                        DownlineCmdInstructionMonitor.Gen3015CmdToGateway(gCtx, pCtx);
                        DownlineCmdInstructionMonitor.Gen3012CmdToGateway(gCtx, pCtx);
                        DownlineCmdInstructionMonitor.Gen3194CmdToGateway(gCtx, pCtx);
                        DownlineCmdInstructionMonitor.Gen3016CmdToGateway(gCtx, pCtx);
                        DownlineCmdInstructionMonitor.Gen1062CmdToGateway(gCtx, pCtx);

                        DownlineCmdInstructionBoth.Gen1011CmdToGateway(gCtx, pCtx);
                    }
                }
                catch (Exception ex)
                {
                    _log.Error(ex);
                }
                finally
                {
                    ThreadUtil.Sleep(milliSeconds);
                }
            }
            // ReSharper disable once FunctionNeverReturns
        }
        //private void ProcessDownData2011(object state)
        //{
        //    while (true)
        //    {
        //        try
        //        {
        //            if (new ArrayList { 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55 }.Contains(DateTime.Now.Minute))
        //            {
        //                var begin = DateTime.Now;
        //                DownlineDataInstructionTotal.Gen2011ToGateway();
        //                var span = (DateTime.Now - begin).TotalMinutes;
        //                if (span < 1)
        //                {
        //                    ThreadUtil.Sleep(1 * 60 * 1000);
        //                }
        //            }
        //        }
        //        catch (Exception ex)
        //        {
        //            _log.Error(ex);
        //        }
        //        finally
        //        {
        //            ThreadUtil.Sleep(1 * 60 * 1000);
        //        }
        //    }
        //    // ReSharper disable once FunctionNeverReturns
        //}
        //private void ProcessDownData2051(object state)
        //{
        //    while (true)
        //    {
        //        try
        //        {
        //            if (new ArrayList { 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55 }.Contains(DateTime.Now.Minute))
        //            {
        //                var begin = DateTime.Now;
        //                DownlineDataInstructionTotal.Gen2051ToGateway();
        //                var span = (DateTime.Now - begin).TotalMinutes;
        //                if (span < 1)
        //                {
        //                    ThreadUtil.Sleep(1 * 60 * 1000);
        //                }
        //            }
        //        }
        //        catch (Exception ex)
        //        {
        //            _log.Error(ex);
        //        }
        //        finally
        //        {
        //            ThreadUtil.Sleep(1 * 60 * 1000);
        //        }
        //    }
        //    // ReSharper disable once FunctionNeverReturns
        //}
        //private void ProcessDownData2061(object state)
        //{
        //    while (true)
        //    {
        //        try
        //        {
        //            if (new ArrayList { 3 }.Contains(DateTime.Now.Minute))
        //            {
        //                var begin = DateTime.Now;
        //                DownlineDataInstructionTotal.Gen2061ToGateway();
        //                var span = (DateTime.Now - begin).TotalMinutes;
        //                if (span < 1)
        //                {
        //                    ThreadUtil.Sleep(1 * 60 * 1000);
        //                }
        //            }
        //        }
        //        catch (Exception ex)
        //        {
        //            _log.Error(ex);
        //        }
        //        finally
        //        {
        //            ThreadUtil.Sleep(1 * 60 * 1000);
        //        }
        //    }
        //    // ReSharper disable once FunctionNeverReturns
        //}

        private void Charging(object state)
        {
            while (true)
            {
                try
                {
                    using (var pCtx = new PlatformContext())
                    {
                        var poll = CommonInformation.GetContamCode("w01018");
                        if (poll != null)
                        {
                            var now = DateTime.Now;
                            if (now.Day == 1 && now.Hour == 4)
                            {
                                var end = new DateTime(now.Year, now.Month, now.Day, 0, 0, 0);
                                var begin = end.AddMonths(-1);
                                var enterprises = pCtx.EnterpriseInfors.ToList();
                                foreach (var enterprise in enterprises)
                                {
                                    var item =
                                        pCtx.缴费账单
                                            .Where(t => t.企业基本信息ID == enterprise.ID)
                                            .FirstOrDefault(t => t.账单日期 >= begin && t.账单日期 < end);
                                    if (item != null) continue;

                                    var charging = CommonInformation.GetCharging();
                                    if (charging == null) continue;

                                    item = new 缴费账单
                                    {
                                        账单日期 = begin,
                                        是否缴费 = "否",
                                        第一阶梯单价 = charging.第一阶梯单价 ?? 2,
                                        第一阶梯排放量 = 0,
                                        第二阶梯单价 = charging.第二阶梯单价,
                                        第二阶梯排放量 = 0,
                                        第三阶梯单价 = charging.第三阶梯单价,
                                        第三阶梯排放量 = 0
                                    };

                                    for (var time = begin; time < end; time = time.AddDays(1))
                                    {
                                        var theTime = time;
                                        var dayIds =
                                            pCtx.DayDataMains.Where(t => t.企业基本信息ID == enterprise.ID)
                                                .Where(t => t.监测时间 >= theTime && t.监测时间 < theTime.AddDays(1))
                                                .Select(t => t.ID);
                                        var dayCou = pCtx.DayDataMains.Where(t => t.企业基本信息ID == enterprise.ID)
                                                .Where(t => t.监测时间 >= theTime && t.监测时间 < theTime.AddDays(1))
                                                .Where(t => t.时段量 != null)
                                               .Sum(t => t.时段量);
                                        var dayMax = pCtx.DayDataDetails.Where(t => dayIds.Contains(t.主日数据ID))
                                            .Where(t => t.污染物编码ID == poll.ID).Where(t => t.Max != null).Max(t => t.Max);
                                        if (charging.第一阶梯上限浓度 == null) charging.第一阶梯上限浓度 = int.MaxValue;
                                        if (charging.第一阶梯上限浓度 >= dayMax)
                                        {
                                            item.第一阶梯排放量 += dayCou.Value;
                                        }
                                        else
                                        {
                                            if (charging.第二阶梯单价 == null)
                                            {
                                                item.第一阶梯排放量 += dayCou.Value;
                                            }
                                            else if (charging.第二阶梯上限浓度 >= dayMax)
                                            {
                                                item.第二阶梯排放量 += dayCou.Value;
                                            }
                                            else
                                            {

                                                if (charging.第三阶梯单价 == null)
                                                {
                                                    item.第二阶梯排放量 += dayCou.Value;
                                                }
                                                else
                                                {
                                                    item.第三阶梯排放量 += dayCou.Value;
                                                }
                                            }
                                        }
                                    }
                                    item.总金额 = item.第一阶梯单价 * item.第一阶梯排放量 + (item.第二阶梯单价 ?? 0) * (item.第二阶梯排放量 ?? 0)
                                               + (item.第三阶梯单价 ?? 0) * (item.第三阶梯排放量 ?? 0);
                                    pCtx.缴费账单.Add(item);
                                    pCtx.SaveChanges();
                                }
                                ThreadUtil.Sleep(75 * 60 * 1000);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    _log.Error(ex);
                }
                finally
                {
                    ThreadUtil.Sleep(10 * 60 * 1000);
                }
            }
            // ReSharper disable once FunctionNeverReturns
        }
        private void ProcessTriger(object state)
        {
            while (true)
            {
                try
                {
                    using (var gCtx = new GatewayMonitorContext())
                    using (var pCtx = new PlatformContext())
                    {
                        var mns = TriggerInfoBuffer.GetInfoKeys();
                        foreach (var mn in mns)
                        {
                            //var mn = mn1;
                            var letport = CommonInformation.GetLetportByMn(mn);
                            if (letport == null) continue;
                            var systemSetup = CommonInformation.GetSystemSetupByName("流量开始触发");
                            if (string.IsNullOrEmpty(systemSetup?.参数内容))
                            {
                                _log.Error("没有设置流量开始触发值(分钟)");
                                continue;
                            }
                            var delayTimeToAnalysis = int.Parse(systemSetup.参数内容.Trim());
                            //_log.Info("流量开始触发值(分钟):" + delayTimeToAnalysis);
                            systemSetup = CommonInformation.GetSystemSetupByName("两次流量触发");
                            if (string.IsNullOrEmpty(systemSetup?.参数内容))
                            {
                                _log.Error("没有设置两次流量触发(分钟)");
                                continue;
                            }
                            var nextTime = int.Parse(systemSetup.参数内容.Trim());
                            var now = DateTime.Now;
                            TriggerInfo info = TriggerInfoBuffer.GetInfo(mn);
                            if (info == null) continue;
                            if (!info.IsSent && now >= info.SentDateTime && now < info.NextSendDateTime)
                            {

                                info.IsSent = true;
                                info.TriggerDateTime = now;
                                info.SentDateTime = info.TriggerDateTime.AddMinutes(delayTimeToAnalysis);
                                info.NextSendDateTime = info.TriggerDateTime.AddMinutes(nextTime + delayTimeToAnalysis);
                                try
                                {
                                    流量触发记录 record = new 流量触发记录
                                    {
                                        企业基本信息ID = letport.企业基本信息ID,
                                        设备信息ID = letport.ID,
                                        时间 = now
                                    };
                                    pCtx.流量触发记录.Add(record);
                                    pCtx.SaveChanges();
                                }
                                catch (Exception e)
                                {
                                    _log.Error(e);
                                }
                                try
                                {
                                    //if (mn.Contains("TINZSC20170020TZ83206006")) mn = "TINZSC20170020TZ83206005";
                                    var result = "QN=" + now.ToString("yyyyMMddHHmmssfff") +
                                                 ";ST=32;CN=4016;PW=123456;MN=" + mn + ";Flag=5;CP=&&&&";
                                    result = Crc.WrapByCrc(result, "monitor");
                                    send_ctr_cmd record = new send_ctr_cmd
                                    {
                                        cn = "4016",
                                        is_sent = false,
                                        mn = mn,
                                        qn = now.ToString("yyyyMMddHHmmssfff"),
                                        send_string = result,
                                        send_time = now,
                                        sent_time = now
                                    };
                                    gCtx.send_ctr_cmd.Add(record);
                                    gCtx.SaveChanges();
                                }
                                catch (Exception e)
                                {
                                    _log.Error(e);
                                }
                            }
                            if (now > info.NextSendDateTime)
                            {
                                info.IsSent = false;
                            }
                        }

                    }
                }
                catch (Exception ex)
                {
                    _log.Error(ex);
                }
                finally
                {
                    ThreadUtil.Sleep(1000);
                }
            }
            // ReSharper disable once FunctionNeverReturns
        }
    }
}
